﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;

namespace BaiduZhiDaoLib
{
    /// <summary>
    /// 状态代理
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void BaiduStatusHandler(object sender, BaiduStatusEventArgs e);
    /// <summary>
    /// 百度知道
    /// </summary>
    public class BaiduZhidao
    {
        private WebBrowser zdWeb;
        private System.Windows.Forms.Timer timer_thread;
        private STATUS runCode = STATUS.Nologin;
        private const int TIMES = 3;
        private int runtimes = TIMES;
        private string account;
        private string password;
        private string title;
        private string message;

        /// <summary>
        /// 状态改变事件
        /// </summary>
        public event BaiduStatusHandler baiduStatus;
        /// <summary>
        /// 抛出状态
        /// </summary>
        /// <param name="url"></param>
        /// <param name="code"></param>
        /// <param name="message"></param>
        private void throwBaiduStatus(string message)
        {
            if (baiduStatus != null)
            {
                BaiduStatusEventArgs e = new BaiduStatusEventArgs(this.zdWeb.Url.ToString(), this.runCode, message);
                baiduStatus(this, e);
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="zdWeb"></param>
        public BaiduZhidao(WebBrowser zdWeb)
        {
            this.zdWeb = zdWeb == null ? new WebBrowser() : zdWeb;
            this.zdWeb.Navigate("http://zhidao.baidu.com/");
            this.zdWeb.DocumentCompleted += zdWeb_DocumentCompleted;//页面加载完成触发事件
            this.zdWeb.Navigated += zdWeb_Navigated;//页面跳转触发事件
            this.zdWeb.Navigating += zdWeb_Navigating;//页面跳转前触发事件
            this.zdWeb.NewWindow += zdWeb_NewWindow;//屏蔽新打开窗口
            this.zdWeb.ScriptErrorsSuppressed = false;
            this.timer_thread = new System.Windows.Forms.Timer();
            this.timer_thread.Interval = 1000;
            this.timer_thread.Tick += timer_thread_Tick;//计时器任务
            //this.timer_thread.Start();
        }
        public void accept(string askid)
        {
            if (this.checkLogin())
            {
                this.zdWeb.Navigate("http://zhidao.baidu.com/question/" + askid + ".html");
                this.runCode = STATUS.Accept;
                this.timer_thread.Start();
            }
            else
            {
                this.runCode = STATUS.Nologin;
            }
        }
        /// <summary>
        /// 回答
        /// </summary>
        /// <param name="askid"></param>
        /// <param name="message"></param>
        public void answer(string askid, string message)
        {
            if (this.checkLogin())
            {
                this.zdWeb.Navigate("http://zhidao.baidu.com/question/" + askid + ".html?push=asking&entry=qb_home_new");
                this.message = message;
                this.runCode = STATUS.Answer;
                this.timer_thread.Start();
            }
            else
            {
                this.runCode = STATUS.Nologin;
            }
        }
        /// <summary>
        /// 提问
        /// </summary>
        /// <param name="title"></param>
        /// <param name="message"></param>
        public void ask(string title, string message)
        {
            if (this.checkLogin())
            {
                this.zdWeb.Document.GetElementById("ask-btn").InvokeMember("click");
                this.title = title;
                this.message = message;
                this.runCode = STATUS.Ask;
                this.timer_thread.Start();
            }
            else
            {
                this.runCode = STATUS.Nologin;
            }
        }
        /// <summary>
        /// 注销
        /// </summary>
        public void logout()
        {
            this.runCode = STATUS.Logout;
            this.timer_thread.Start();
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="account"></param>
        /// <param name="password"></param>
        public void login(string account, string password)
        {
            this.account = account;
            this.password = password;
            if (!this.checkLogin())
            {
                this.runCode = STATUS.Login;
                this.timer_thread.Start();
            }
            else
            {
                throwBaiduStatus("您已经登录");
            }
        }

        /// <summary>
        /// 检测登录状态
        /// </summary>
        /// <returns></returns>
        public bool checkLogin()
        {
            return checkLogin(true);
        }
        /// <summary>
        /// 检测登录状态
        /// </summary>
        /// <param name="isFlash"></param>
        /// <returns></returns>
        public bool checkLogin(bool isFlash)
        {
            bool ret = null != this.zdWeb.Document.GetElementById("userbar-logout");
            if (isFlash)
            {
                this.runCode = ret ? STATUS.Logineded : STATUS.Nologin;
            }
            return ret;
        }
        /// <summary>
        /// 填写验证码
        /// </summary>
        /// <param name="code"></param>
        public void setImageCode(string code)
        {
            this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__verifyCode").Focus();
            this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__verifyCode").SetAttribute("value", code);
            this.runCode = STATUS.Logining;
            this.timer_thread.Start();
        }
        /// <summary>
        /// 计时器任务
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer_thread_Tick(object sender, EventArgs e)
        {
            switch (this.runCode)
            {
                case STATUS.Accept:
                    {
                        bool ret = false;
                        try
                        {
                            HtmlElementCollection hec = this.zdWeb.Document.GetElementsByTagName("a");
                            foreach (HtmlElement he in hec)
                            {
                                if ("qb-adopt-ask" == he.GetAttribute("alog-action"))
                                {
                                    ret = true;
                                    break;
                                }
                            }
                        }
                        catch (Exception ex)
                        {

                        }
                        if (ret)
                        {
                            this.timer_thread.Stop();
                            HtmlElementCollection hec = this.zdWeb.Document.GetElementsByTagName("a");
                            foreach (HtmlElement he in hec)
                            {
                                if ("qb-adopt-ask" == he.GetAttribute("alog-action"))
                                {
                                    he.InvokeMember("click");
                                }
                            }
                            this.runtimes = TIMES;
                            this.runCode = STATUS.Accepted;
                            throwBaiduStatus("采纳成功");
                        }
                        else if (this.runtimes-- < 1)
                        {
                            this.timer_thread.Stop();
                            this.checkLogin(false);
                            this.runtimes = TIMES;
                            this.runCode = STATUS.Error;
                            throwBaiduStatus("采纳失败/已经采纳");
                        }
                        break;
                    }
                case STATUS.Answer:
                    {
                        bool ret = this.zdWeb.Document.GetElementById("answer-bar") != null; ;
                        //try
                        //{
                        //    ret = this.zdWeb.Document.Window.Frames.Count > 0 ? this.zdWeb.Document.Window.Frames["ueditor_0"] != null : false;
                        //}
                        //catch (Exception ex)
                        //{

                        //}
                        if (ret)
                        {
                            if (this.zdWeb.Document.GetElementById("answer-bar").Children[0].OuterHtml.Equals("<i class=\"i-arrow-down\"></i>"))
                            {
                                this.zdWeb.Document.GetElementById("answer-bar").InvokeMember("click");
                            }
                            this.zdWeb.Document.Window.Frames["ueditor_0"].Document.Body.InnerHtml = "<p>" + this.message + "</p>";
                            HtmlElementCollection hec = this.zdWeb.Document.GetElementsByTagName("a");
                            foreach (HtmlElement he in hec)
                            {
                                if ("qb-ans-sb" == he.GetAttribute("alog-action"))
                                {
                                    he.InvokeMember("click");
                                    break;
                                }
                            }
                            this.runCode = STATUS.Answered;
                            this.runtimes = TIMES;
                        }
                        else if (this.runtimes-- < 1)
                        {
                            this.timer_thread.Stop();
                            this.checkLogin(false);
                            this.runtimes = TIMES;
                            this.runCode = STATUS.Error;
                            throwBaiduStatus("回答失败");
                        }

                        break;
                    }
                case STATUS.Answered:
                    {
                        this.timer_thread.Stop();
                        throwBaiduStatus("回答成功");
                        break;
                    }
                case STATUS.Ask:
                    {
                        bool ret = this.zdWeb.Document.GetElementById("ask-btn") != null;
                        if (ret)
                        {
                            bool ret1 = this.zdWeb.Document.GetElementById("title-area") != null;
                            if (ret1)
                            {
                                this.runCode = STATUS.Asking;
                                this.runtimes = TIMES;
                            }
                            else if (this.runtimes-- < 1)
                            {
                                this.checkLogin(false);
                                this.runtimes = TIMES;
                                this.runCode = STATUS.Error;
                                throwBaiduStatus("提问失败");
                            }
                        }
                        else
                        {
                            this.runCode = STATUS.Nologin;
                                                        
                        }
                        break;
                    }
                case STATUS.Asking:
                    {
                        if (this.zdWeb.Document.GetElementById("userbar-logout") != null && this.zdWeb.Document.GetElementById("userbar-logout") != null)
                        {
                            this.zdWeb.Document.GetElementById("title-area").Focus();
                            this.zdWeb.Document.GetElementById("title-area").SetAttribute("value", this.title);
                            this.zdWeb.Document.GetElementById("phone").InvokeMember("click");
                            this.zdWeb.Document.GetElementById("submit-btn").InvokeMember("click");
                            this.zdWeb.Document.Window.Frames["ueditor_0"].Document.Body.Focus();
                            this.zdWeb.Document.Window.Frames["ueditor_0"].Document.Body.InnerHtml = "<p>" + this.message + "</p>";
                            this.runtimes = TIMES;
                            this.runCode = STATUS.Asked;
                        }
                        else if (this.runtimes-- < 1)
                        {
                            this.checkLogin(false);
                            this.runtimes = TIMES;
                            this.runCode = STATUS.Error;
                            throwBaiduStatus("提问失败");
                        }
                        break;
                    }
                case STATUS.Asked:
                    {
                        string url = this.zdWeb.Url.ToString();
                        //http://zhidao.baidu.com/question/1733380527380758147.html
                        Regex regex = new Regex("http://zhidao\\.baidu\\.com/question/[0-9]*\\.html");
                        Match match = regex.Match(url);
                        if (match.Success)
                        {
                            this.timer_thread.Stop();
                            string id = url.Substring(url.LastIndexOf('/') + 1).Replace(".html", string.Empty); ;
                            this.throwBaiduStatus(id);
                            this.runtimes = TIMES;
                        }
                        else if (this.runtimes-- < 1)
                        {
                            this.timer_thread.Stop();
                            this.checkLogin(false);
                            this.runtimes = TIMES;
                            this.runCode = STATUS.Error;
                            throwBaiduStatus("提问失败");
                        }                        
                        break;
                    }                
                case STATUS.Nologin:
                    {
                        this.timer_thread.Stop();
                        throwBaiduStatus("未登录/登录失败");
                        break;
                    }
                case STATUS.Login:
                    {
                        bool ret = this.zdWeb.Document.GetElementById("userbar-login") != null;
                        if (ret)
                        {
                            this.zdWeb.Document.GetElementById("userbar-login").InvokeMember("click");
                            this.runCode = STATUS.Logining;
                            this.runtimes = 0;
                        }
                        if (this.runtimes-- < 1)
                        {
                            this.checkLogin(false);
                            this.runtimes = TIMES;
                        }
                       
                        break;
                    }
                case STATUS.Logining:
                    {
                        bool ret1 = this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__userName") != null;
                        if (ret1)
                        {
                            this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__userName").Focus();
                            this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__userName").SetAttribute("value", this.account);
                        }
                        bool ret2 = this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__password") != null;
                        if (ret2)
                        {
                            this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__password").Focus();
                            this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__password").SetAttribute("value", this.password);
                        }
                        bool ret4=this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__memberPass") != null;
                        if (ret4)
                        {
                            if (this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__memberPass").GetAttribute("checked") == "True")
                            {
                                this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__memberPass").InvokeMember("click");
                            }
                        }
                        bool ret3 = this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__submit") != null;
                        if (ret3)
                        {
                            this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__submit").InvokeMember("click");
                        }

                        if (ret1 && ret2 && ret3)
                        {
                            this.runCode = STATUS.Logined;
                        }

                        if (this.runtimes-- < 1)
                        {
                            this.checkLogin(false);
                            this.runtimes = TIMES;
                        }
                        break;
                    }
                case STATUS.Logout:
                    {
                        if (this.zdWeb.Document.GetElementById("userbar-logout") != null)
                        {
                            this.timer_thread.Stop();
                            this.runCode = STATUS.Logouted;
                            this.zdWeb.Document.GetElementById("userbar-logout").InvokeMember("click");
                            throwBaiduStatus("注销成功");
                        }
                        break;
                    }
                case STATUS.Logined:
                    {
                        if (this.runtimes-- < 0)
                        {
                            this.runtimes = TIMES;
                            this.checkLogin();
                        }
                        else if (this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__verifyCodeImg") != null)
                        {
                            this.runtimes = TIMES;
                            this.runCode = STATUS.Image;
                        }
                        break;
                    }
                case STATUS.Image:
                    {
                        if (this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__verifyCodeImg") != null)
                        {
                            this.timer_thread.Stop();
                            this.runtimes = TIMES;
                            throwBaiduStatus(this.zdWeb.Document.GetElementById("TANGRAM__PSP_8__verifyCodeImg").GetAttribute("src"));
                        }
                        else if (this.runtimes-- < 0)
                        {
                            this.runtimes = TIMES;
                            this.checkLogin();
                        }
                        break;
                    }
                case STATUS.Logineded:
                    { 
                        if (this.runtimes-- < 0)
                        {
                            this.timer_thread.Stop();
                            throwBaiduStatus("您已经登录");
                            this.runtimes = TIMES;
                        }
                        break;
                    }
                default:
                    {
                        this.timer_thread.Stop();
                        MessageBox.Show("undefined");
                        this.runCode = STATUS.Nologin;
                        break;
                    }
            }
        }

        /// <summary>
        /// 屏蔽新打开窗口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void zdWeb_NewWindow(object sender, CancelEventArgs e)
        {
            e.Cancel = true;
        }

        /// <summary>
        /// 页面跳转前触发事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void zdWeb_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            
        }

        /// <summary>
        /// 页面跳转触发事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void zdWeb_Navigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            
        }

        /// <summary>
        /// 页面加载完成触发事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void zdWeb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            
        }
    }
}
